home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / bbs_util / bsrc_260.zip / SRC.ZIP / XMREC.C < prev    next >
C/C++ Source or Header  |  1996-02-20  |  31KB  |  1,323 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
  11. /*                                                                          */
  12. /*                  This module was written by Bob Hartman                  */
  13. /*                                                                          */
  14. /*                BinkleyTerm Xmodem Receiver State Machine                 */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*    For complete  details  of the licensing restrictions, please refer    */
  18. /*    to the License  agreement,  which  is published in its entirety in    */
  19. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
  20. /*                                                                          */
  21. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  22. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  23. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  24. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  25. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  26. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  27. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  28. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  29. /*                                                                          */
  30. /*                                                                          */
  31. /* You can contact Bit Bucket Software Co. at any one of the following      */
  32. /* addresses:                                                               */
  33. /*                                                                          */
  34. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
  35. /* P.O. Box 460398                AlterNet 7:42/1491                        */
  36. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  37. /*                                Internet f491.n343.z1.fidonet.org         */
  38. /*                                                                          */
  39. /* Please feel free to contact us at any time to share your comments about  */
  40. /* our software and/or licensing policies.                                  */
  41. /*                                                                          */
  42. /*--------------------------------------------------------------------------*/
  43.  
  44. /* Include this file before any other includes or defines! */
  45.  
  46. #include "includes.h"
  47.  
  48. void Find_Char (int);
  49. int Header_in_data (unsigned char *);
  50. void Send_ACK (XMARGSP);
  51. void Send_NAK (XMARGSP);
  52. long Open_Xmodem_File (XMARGSP);
  53.  
  54. int XRInit (XMARGSP);
  55. int XREnd (XMARGSP);
  56. int XRRecInit (XMARGSP);
  57. int XRBrecInit (XMARGSP);
  58. int XRRecStart (XMARGSP);
  59. int XRWaitFirst (XMARGSP);
  60. int XRWaitBlock (XMARGSP);
  61. int XRRestart (XMARGSP);
  62. int XRSetOvrdr (XMARGSP);
  63.  
  64. typedef struct
  65. {
  66.     char *state_name;
  67.     int (*state_func) (XMARGSP);
  68. } XSTATES, *XSTATEP;
  69.  
  70. XSTATES Xmodem_Receiver[] =
  71. {
  72.     {"XRInit", XRInit},
  73.     {"XREnd", XREnd},
  74.     {"XR0", XRRecInit},
  75.     {"XR0B", XRBrecInit},
  76.     {"XR1", XRRecStart},
  77.     {"XR2", XRWaitFirst},
  78.     {"XR3", XRWaitBlock},
  79.     {"XR4", XRRestart},
  80.     {"XR5", XRSetOvrdr}
  81. };
  82.  
  83. long 
  84. Open_Xmodem_File (XMARGSP args)
  85. {
  86.     char *s1, *s2;
  87.  
  88.     if (args->file_pointer == NULL)
  89.     {
  90.         args->temp_name = calloc (1, 80);
  91.  
  92.         if (args->path != NULL)
  93.             (void) strcpy (args->temp_name, args->path);
  94.  
  95.         s1 = &(args->temp_name[strlen (args->temp_name)]);
  96.         (void) strcpy (s1, "BTXXXXXX");
  97.         s2 = mktemp (args->temp_name);
  98.         if ((s2 == NULL) || ((args->file_pointer = fopen (s2, write_binary)) == NULL))
  99.         {
  100.             status_line (MSG_TXT (M_TEMP_NOT_OPEN), s2);
  101.             return (-1L);
  102.         }
  103.     }
  104.  
  105.     throughput (0, 0L);
  106.     return (0L);
  107. }
  108.  
  109. long 
  110. Set_Up_Restart (XMARGSP args)
  111. {
  112.     char foo[100];
  113.     char foo1[50];
  114.     struct stat st;
  115.  
  116.     args->sub_results = 0;
  117.  
  118.     /* Look for file in directory */
  119.     if (args->path != NULL)
  120.         (void) strcpy (foo, args->path);
  121.  
  122.     if ((args->received_name != NULL) &&
  123.         (strlen (args->received_name) > 0) &&
  124.         args->options.Resync)
  125.     {
  126.         (void) strcat (foo, args->received_name);
  127.  
  128.         if (stat (foo, &st) == 0)
  129.         {
  130.             if ((st.st_size == args->filelen) && (st.st_atime == (time_t) (args->save_filetime.oneword.timedate)))
  131.             {
  132.                 if ((args->file_pointer = fopen (foo, "rb+")) != NULL)
  133.                 {
  134.                     throughput (0, 0L);
  135.                     (void) fseek (args->file_pointer, 0L, SEEK_END);
  136.                     args->sub_results = DID_RESYNC;
  137.                     args->temp_name = calloc (1, 80);
  138.                     (void) strcpy (args->temp_name, foo);
  139.                     args->prev_bytes = args->filelen;
  140.                     status_line (MSG_TXT (M_ALREADY_HAVE), foo);
  141.                     status_line (MSG_TXT (M_SYNCHRONIZING_EOF));
  142.                     return (args->total_blocks + 1L);
  143.                 }
  144.             }
  145.         }
  146.  
  147.         /* Look for file in .Z file */
  148.         if (dexists (Abortlog_name))
  149.         {
  150.             (void) sprintf (Resume_info, "%ld %lo", args->filelen, args->save_filetime.oneword.timedate);
  151.             if (check_failed (Abortlog_name, args->received_name, Resume_info, foo1))
  152.             {
  153.                 foo[0] = '\0';
  154.                 /* Here it looks like it was a failed WaZOO session */
  155.                 if (args->path != NULL)
  156.                     (void) strcpy (foo, args->path);
  157.                 (void) strcat (foo, foo1);
  158.  
  159.                 if ((args->file_pointer = fopen (foo, "rb+")) != NULL)
  160.                 {
  161.                     (void) stat (foo, &st);
  162.                     throughput (0, 0L);
  163.                     args->temp_name = calloc (1, 80);
  164.                     (void) strcpy (args->temp_name, foo);
  165.                     args->prev_bytes = (st.st_size / 128L) * 128L;
  166.                     (void) fseek (args->file_pointer, args->prev_bytes, SEEK_SET);
  167.                     status_line (MSG_TXT (M_SYNCHRONIZING_OFFSET), args->prev_bytes);
  168.                     return (args->prev_bytes / 128L + 1L);
  169.                 }
  170.             }
  171.         }
  172.     }
  173.  
  174.     return (Open_Xmodem_File (args));
  175. }
  176.  
  177. void 
  178. Finish_Xmodem_Receive (XMARGSP args)
  179. {
  180.     struct stat st;
  181.     char new_name[80];
  182.     struct utimbuf times;
  183.     int i, j, k;
  184.  
  185.     /* Set the file's time and date stamp */
  186.     if ((args->save_header == SOH) || (args->save_header == SYN))
  187.     {
  188.         (void) fclose (args->file_pointer);
  189.         times.modtime = times.UT_ACTIME = (time_t) args->save_filetime.oneword.timedate;
  190.         (void) utime (args->temp_name, (UTIMBUF *) & times);
  191.     }
  192.     else
  193.     {
  194.         (void) strcpy (args->received_name, "");
  195.         if (args->file_pointer)
  196.             (void) fclose (args->file_pointer);
  197.     }
  198.  
  199.     if (args->result == SUCCESS)
  200.     {
  201.         long lFileTime;
  202.         long lFileSize;
  203.  
  204.         /* Get the file information */
  205.         (void) stat (args->temp_name, &st);
  206.  
  207.         lFileSize = st.st_size - args->prev_bytes;
  208.         lFileTime = throughput (1, (unsigned long)lFileSize);
  209.  
  210.         if (args->sub_results & DID_RESYNC)
  211.         {
  212.             status_line ("%s: %s", MSG_TXT (M_FILE_RECEIVED), args->temp_name);
  213.             update_files (0, args->temp_name, lFileSize, lFileTime, 0);
  214.         }
  215.         else
  216.         {
  217.             new_name[0] = '\0';
  218.             if (args->path != NULL)
  219.                 (void) strcpy (new_name, args->path);
  220.             if ((args->filename == NULL) || (strlen (args->filename) == 0))
  221.             {
  222.                 if (strlen (args->received_name) > 0)
  223.                     (void) strcat (new_name, args->received_name);
  224.                 else
  225.                     (void) strcat (new_name, "BAD_FILE.000");
  226.             }
  227.             else
  228.             {
  229.                 (void) strcat (new_name, args->filename);
  230.             }
  231.  
  232.             i = (int) strlen (args->temp_name) - 1;
  233.             j = (int) strlen (new_name) - 1;
  234.  
  235.             if (args->temp_name[i] == '.')
  236.                 args->temp_name[i] = '\0';
  237.             if (new_name[j] == '.')
  238.             {
  239.                 new_name[j] = '\0';
  240.                 --j;
  241.             }
  242.  
  243.             i = 0;
  244.             k = is_arcmail (new_name, j);
  245.  
  246.             status_line ("%s: %s", MSG_TXT (M_FILE_RECEIVED), new_name);
  247.             update_files (0, new_name, lFileSize, lFileTime, 0);
  248.  
  249.             if ((!overwrite) || k)
  250.             {
  251.                 while (rename (args->temp_name, new_name))
  252.                 {
  253.                     if (isdigit (new_name[j]))
  254.                         new_name[j]++;
  255.                     else
  256.                         new_name[j] = '0';
  257.                     if (!isdigit (new_name[j]))
  258.                     {
  259.                         return;
  260.                     }
  261.                     i = 1;
  262.                 }
  263.                 CLEAR_IOERR ();
  264.             }
  265.             else
  266.             {
  267.                 (void) unlink (new_name);
  268.                 while (rename (args->temp_name, new_name))
  269.                 {
  270.                     if (!i)
  271.                     {
  272.                         status_line (MSG_TXT (M_ORIGINAL_NAME_BAD), new_name);
  273.                     }
  274.                     if (isdigit (new_name[j]))
  275.                         new_name[j]++;
  276.                     else
  277.                         new_name[j] = '0';
  278.                     if (!isdigit (new_name[j]))
  279.                     {
  280.                         return;
  281.                     }
  282.                     i = 1;
  283.                 }
  284.                 CLEAR_IOERR ();
  285.             }
  286.             if (i)
  287.             {
  288.                 if (locate_y && !(fullscreen && un_attended))
  289.                     gotoxy (2, locate_y - 1);
  290.                 status_line (MSG_TXT (M_RENAME_MSG), new_name);
  291.             }
  292.         }
  293.  
  294.         remove_abort (Abortlog_name, args->received_name);
  295.     }
  296.     else
  297.     {
  298.         if ((args->received_name != NULL) && (strlen (args->received_name) > 0) && (args->save_header != 0))
  299.         {
  300.             (void) sprintf (Resume_info, "%ld %lo", args->filelen, args->save_filetime.oneword.timedate);
  301.             add_abort (Abortlog_name, args->received_name, args->temp_name, args->path, Resume_info);
  302.         }
  303.         else
  304.         {
  305.             /* File aborted, so remove all traces of it */
  306.             if (args->temp_name != NULL)
  307.                 (void) unlink (args->temp_name);
  308.         }
  309.     }
  310.  
  311.     if (args->temp_name != NULL)
  312.     {
  313.         free (args->temp_name);
  314.     }
  315. }
  316.  
  317. void 
  318. Get_Telink_Info (XMARGSP args)
  319. {
  320.     char *p1;
  321.     char junkbuff[100];
  322.     TLDATAP t;
  323.     unsigned int i, j;
  324.     struct tm tmstruc;
  325.     time_t curr_time;
  326.  
  327.     /* Figure out how many blocks we will get */
  328.     t = (TLDATAP) & (args->header);
  329.     args->total_blocks = (t->filelength + 127) / 128;
  330.     t->nullbyte = '\0';
  331.     p1 = strchr (t->filename, ' ');
  332.     if (p1 != NULL)
  333.         *p1 = '\0';
  334.  
  335.     /* Rename .REQ files */
  336.  
  337.     i = strlen (t->filename) - 4;
  338.     if ((i > 0) && (stricmp (&(t->filename)[i], ".REQ") == 0))
  339.     {
  340.         (t->filename)[i] = '\0';
  341.         status_line (MSG_TXT(M_REC_REQ_AS), t->filename, t->filename, TaskNumber);
  342.         sprintf (&(t->filename)[i],".R%02x", TaskNumber);
  343.     }
  344.  
  345.     (void) strcpy (args->received_name, t->filename);
  346.     args->save_header = args->header;
  347.     if (args->save_header == SYN)
  348.     {
  349.         i = t->filetime.twowords.time;
  350.         j = t->filetime.twowords.date;
  351.  
  352.         curr_time = time (NULL);
  353.         tmstruc = *localtime (&curr_time);    /* Structure assignment */
  354.  
  355.         tmstruc.tm_year = (j >> 9) + 80;
  356.         tmstruc.tm_mon = ((j >> 5) & 0x0f) - 1;
  357.         tmstruc.tm_mday = j & 0x1f;
  358.  
  359.         tmstruc.tm_hour = i >> 11;
  360.         tmstruc.tm_min = (i >> 5) & 0x3f;
  361.         tmstruc.tm_sec = i & 0x1f;
  362.  
  363.         args->save_filetime.oneword.timedate = mktime (&tmstruc);
  364.     }
  365.     else
  366.     {
  367. #ifdef ANSI_TIME_T
  368.         args->save_filetime.oneword.timedate = t->filetime.oneword.timedate + ANSI_TIME_T_DELTA;
  369. #else
  370.         args->save_filetime.oneword.timedate = t->filetime.oneword.timedate;
  371. #endif
  372.     }
  373.     args->filelen = t->filelength;
  374.     (void) sprintf (junkbuff, MSG_TXT (M_RECEIVE_MSG),
  375.         args->total_blocks, t->filename, t->sendingprog, t->filelength);
  376.  
  377.     (void) strncpy (args->sending_program, t->sendingprog, 15);
  378.     if (un_attended && fullscreen)
  379.     {
  380.         clear_filetransfer ();
  381.         sb_move (filewin, 1, 2);
  382.         sb_puts (filewin, junkbuff);
  383.         elapse_time ();
  384.         sb_show ();
  385.     }
  386.     else
  387.     {
  388.         status_line ("+%s", junkbuff);
  389.         (void) printf ("\n");
  390.         locate_y = wherey ();
  391.         locate_x = wherex ();
  392.     }
  393. }
  394.  
  395. int 
  396. Read_Block (XMARGSP args)
  397. {
  398.     unsigned char *p;            /* Pointers to XMODEM data */
  399.     int i;                        /* Counter */
  400.     int j;                        /* Counter start */
  401.     unsigned char c;            /* character being processed */
  402.     int in_char;
  403.     char junkbuff[128];
  404.     long head_timer;
  405.  
  406.     struct _pkthdr *packet;        /* FTS-0001 packet type */
  407.     struct _pkthdr45 *pkt0045;    /* FSC-0045 packet type */
  408.     struct _pkthdr39 *pkt0039;    /* FSC-0039 packet type */
  409.  
  410.     unsigned int cwtest;        /* Used to verify FSC-0039 type */
  411.  
  412.     if (got_ESC ())
  413.     {
  414.         status_line (MSG_TXT (M_KBD_MSG));
  415.         return (KBD_ERR);
  416.     }
  417.  
  418.     /* Set up to point into the XMODEM data structure */
  419.     p = (unsigned char *) &(args->header);
  420.  
  421.     /* Get the first character that is waiting */
  422.     *p = (unsigned char) TIMED_READ (8);
  423.  
  424.     head_timer = timerset (6000);
  425.     j = 1;
  426.     while (!timeup (head_timer))
  427.     {
  428.         /* Now key off of the header character */
  429.         switch (*p)
  430.         {
  431.         case EOT:                /* End of file */
  432.             /* Is this a valid EOT */
  433.             if (args->total_blocks <= args->WriteBLK)
  434.             {
  435.                 return (EOT_BLOCK);
  436.             }
  437.             else
  438.             {
  439.                 status_line (MSG_TXT (M_UNEXPECTED_EOF), args->total_blocks);
  440.                 return (BAD_BLOCK);
  441.             }
  442.  
  443.         case SYN:                /* Telink block */
  444.             /* For Telink, read all of the data except the checksum */
  445.             for (i = 1; i < sizeof (TLDATA) - 2; i++)
  446.             {
  447.                 /* If we go more than 5 second, then we have a short block */
  448.                 if ((in_char = TIMED_READ (5)) < 0)
  449.                 {
  450.                     return (BAD_BLOCK);
  451.                 }
  452.                 *(++p) = (unsigned char) (in_char & 0xff);
  453.             }
  454.  
  455.             /* if the block number or its complement are wrong, return error */
  456.             if ((args->block_num != 0) || (args->block_num_comp != 0xff))
  457.             {
  458.                 return (BAD_BLOCK);
  459.             }
  460.  
  461.             /* Now calculate the checksum - Telink block always checksum mode */
  462.             Data_Check ((XMDATAP) & (args->header), CHECKSUM);
  463.  
  464.             /* See if we can receive the checksum byte */
  465.             if ((in_char = TIMED_READ (10)) < 0)
  466.             {
  467.                 Xmodem_Error (MSG_TXT (M_TIMEOUT), 0L);
  468.                 return (BAD_BLOCK);
  469.             }
  470.  
  471.             /* Was it right */
  472.             c = (unsigned char) (in_char & 0xff);
  473.             if (c != args->data_check[0])
  474.             {
  475.                 Xmodem_Error (MSG_TXT (M_CHECKSUM), 0L);
  476.                 return (BAD_BLOCK);
  477.             }
  478.             /* Everything looks good, it must be a legal TELINK block */
  479.  
  480.             Get_Telink_Info (args);
  481.             return (TELINK_BLOCK);
  482.  
  483.         case SOH:                /* Normal data block */
  484.             args->datalen = 128;
  485.             /* Read in all of the data for an XMODEM block except the checksum */
  486.             p += (j - 1);
  487.             for (i = j; i < sizeof (XMDATA) - 2; i++)
  488.             {
  489.                 /* If we go more than 5 seconds, then it is a short block */
  490.                 if ((in_char = TIMED_READ (5)) < 0)
  491.                 {
  492.                     return (BAD_BLOCK);
  493.                 }
  494.                 *(++p) = (unsigned char) (in_char & 0xff);
  495.             }
  496.  
  497.             /* The block number is 0 to 255 inclusive */
  498.             c = (unsigned char) (args->blocknum & 0xff);
  499.  
  500.             /* Properly calculate the CRC or checksum */
  501.             Data_Check ((XMDATAP) & (args->header), args->options.do_CRC ? CRC : CHECKSUM);
  502.  
  503.             /* Can we get the checksum byte */
  504.             if ((in_char = TIMED_READ (10)) < 0)
  505.             {
  506.                 Xmodem_Error (MSG_TXT (M_TIMEOUT), args->WriteBLK);
  507.                 return (BAD_BLOCK);
  508.             }
  509.  
  510.             /* Is it the right value */
  511.             c = (unsigned char) (in_char & 0xff);
  512.             if (c != args->data_check[0])
  513.             {
  514.                 status_line (">Xmodem Receive: Bad %s", (args->options.do_CRC) ? "CRC" : "checksum");
  515.                 Xmodem_Error (MSG_TXT (M_CRC_MSG), args->WriteBLK);
  516.                 if (args->options.do_CRC)
  517.                     (void) TIMED_READ (5);
  518.                 return (BAD_BLOCK);
  519.             }
  520.  
  521.             /* If we are in CRC mode, do the second byte */
  522.             if (args->options.do_CRC)
  523.             {
  524.                 /* Can we get the character */
  525.                 if ((in_char = TIMED_READ (10)) < 0)
  526.                 {
  527.                     status_line (">Xmodem Receive: Timeout waiting for CRC byte 2");
  528.                     Xmodem_Error (MSG_TXT (M_TIMEOUT), args->WriteBLK);
  529.                     return (BAD_BLOCK);
  530.                 }
  531.                 /* Is it right */
  532.                 c = (unsigned char) (in_char & 0xff);
  533.                 if (c != args->data_check[1])
  534.                 {
  535.                     Xmodem_Error (MSG_TXT (M_CRC_MSG), args->WriteBLK);
  536.                     return (BAD_BLOCK);
  537.                 }
  538.             }
  539.  
  540.             /* Do we have a valid data block */
  541.             if (args->block_num_comp != (unsigned char) ((~(args->block_num)) & 0xff))
  542.             {
  543.                 if (!(args->options.SEAlink))
  544.                 {
  545.                     Xmodem_Error (MSG_TXT (M_JUNK_BLOCK), args->WriteBLK);
  546.                     return (BAD_BLOCK);
  547.                 }
  548.  
  549.                 p = (unsigned char *) &(args->header);
  550.                 j = Header_in_data (p);
  551.                 if (j)
  552.                 {
  553.                     continue;
  554.                 }
  555.  
  556.                 j = 1;
  557.                 Find_Char (SOH);
  558.                 *p = (unsigned char) TIMED_READ (0);
  559.             }
  560.  
  561.             if ((args->WriteBLK == 1) && (args->header == SOH) && (args->block_num == 0))
  562.             {
  563.                 Get_Telink_Info (args);
  564.                 return (SEALINK_BLOCK);
  565.             }
  566.  
  567.             if (first_block)
  568.             {
  569.                 packet = (struct _pkthdr *) args->data;
  570.                 pkt0045 = (struct _pkthdr45 *) packet;
  571.                 pkt0039 = (struct _pkthdr39 *) packet;
  572.  
  573.                 if (!remote_capabilities)
  574.                 {
  575.                     remote_addr.Net = packet->orig_net;
  576.                     remote_addr.Node = packet->orig_node;
  577.                     if (packet->rate == 2)
  578.                     {
  579.                         /* This is a FSC-0045 (type 2.2) packet! */
  580.                         remote_addr.Zone = packet->orig_zone;
  581.                         remote_addr.Point = (unsigned) pkt0045->orig_point;
  582.  
  583.                         strncpy (junkbuff, (char *) (pkt0045->orig_domain), 8);
  584.                         junkbuff[8] = '\0';
  585.                         remote_addr.Domain = find_domain (junkbuff);
  586.                     }
  587.                     else
  588.                     {
  589.                         remote_addr.Domain = NULL;
  590.                         cwtest = (((pkt0039->CapValid) & 0x7f00) >> 8) +
  591.                             (((pkt0039->CapValid) & 0x007f) << 8);
  592.                         if (cwtest == (unsigned int) ((pkt0039->CapWord) & 0x7f7f))
  593.                         {
  594.                             /* This is a FSC-0039 packet! */
  595.                             remote_addr.Zone = pkt0039->orig_zone;
  596.                             remote_addr.Point = pkt0039->orig_point;
  597.                         }
  598.                         else
  599.                         {
  600.                             remote_addr.Zone = packet->orig_zone;
  601.                             remote_addr.Point = 0;
  602.                         }
  603.                     }
  604. /*
  605.  * Here we have extracted the Zone, Net, Node, Point and Domain from the
  606.  * packet -- regardless of type. Now see if we need to map to a fake net
  607.  * or to mung the address because it's someone else's point.
  608.  */
  609.                     if ((remote_addr.Point > 0) &&
  610.                         (pvtnet >= 0) &&
  611.                         ((remote_addr.Zone == alias[assumed].Zone) || (remote_addr.Zone == 0)) &&
  612.                         (remote_addr.Net == boss_addr.Net) &&
  613.                         (remote_addr.Node == boss_addr.Node))
  614.                     {
  615.                         remote_addr.Net = pvtnet;
  616.                         remote_addr.Node = remote_addr.Point;
  617.                         remote_addr.Point = 0;
  618.                     }
  619.                     else if ((pvtnet >= 0) && (remote_addr.Point > 0))
  620.                     {
  621.                         remote_addr.Point = 0;
  622.                         remote_addr.Node = (unsigned short) -1;
  623.                     }
  624.                 }
  625.  
  626.                 if (who_is_he)
  627.                 {
  628.                     if (!remote_addr.Zone && !remote_addr.Net && !remote_addr.Node)
  629.                     {
  630.                         LOWER_DTR ();    /* Bad trip, cut it off */
  631.                         timer (2);    /* Wait two secs        */
  632.                         return (CARRIER_ERR);    /* Get out of here!     */
  633.                     }
  634.  
  635.                     if (nodefind (&remote_addr, 1))
  636.                     {
  637.                         if (!remote_addr.Zone)
  638.                             remote_addr.Zone = found_zone;
  639.  
  640.                         (void) sprintf (junkbuff, "%s: %s (%s)",
  641.                             MSG_TXT (M_REMOTE_SYSTEM),
  642.                             newnodedes.SystemName,
  643.                             Full_Addr_Str (&remote_addr));
  644.                     }
  645.                     else
  646.                     {
  647.                         (void) sprintf (junkbuff, "%s: %s (%s)",
  648.                             MSG_TXT (M_REMOTE_SYSTEM),
  649.                             MSG_TXT (M_UNKNOWN_MAILER),
  650.                             Full_Addr_Str (&remote_addr));
  651.                     }
  652.  
  653.                     last_type (2, &remote_addr);
  654.                     status_line (junkbuff);
  655.                 }
  656.                 if (args->sending_program[0] != '\0')
  657.                 {
  658.                     status_line ("%s %s", MSG_TXT (M_REMOTE_USES), args->sending_program);
  659.                 }
  660.                 else
  661.                 {
  662.                     log_product (packet->product, 0, packet->serial);
  663.                 }
  664.                 who_is_he = 0;
  665.                 first_block = 0;
  666.             }
  667.  
  668.             if (args->WriteBLK == args->total_blocks)
  669.             {
  670.                 args->datalen = (int) (args->filelen - ((args->WriteBLK - 1) * 128));
  671.             }
  672.  
  673.             /* If we got this far, it is a valid data block */
  674.             args->recblock = args->block_num;
  675.             return (XMODEM_BLOCK);
  676.  
  677.         default:                /* Bad block */
  678.             if ((args->blocknum <= 1) || (PEEKBYTE () < 0))
  679.                 return (BAD_BLOCK);
  680.  
  681.             /* Garbage header, return bad */
  682.             *p = (unsigned char) TIMED_READ (0);
  683.         }
  684.     }
  685.     return (BAD_BLOCK);
  686. }
  687.  
  688. int 
  689. XRInit (XMARGSP args)
  690. {
  691.     char *HoldName;
  692.  
  693.     args->tries = 0;
  694.     args->goodfile = 1;
  695.     XON_DISABLE ();
  696.     HoldName = HoldAreaNameMunge (&called_addr);
  697.     (void) sprintf (Abortlog_name, "%s%s.Z\0",
  698.         HoldName, Hex_Addr_Str (&remote_addr));
  699.     args->sending_program[0] = '\0';
  700.     return ((int) args->control);
  701. }
  702.  
  703. int 
  704. XREnd (XMARGSP args)
  705. {
  706.     args->result = (int) args->control;
  707.     Finish_Xmodem_Receive (args);
  708.     return ((int) args->control);
  709. }
  710.  
  711. int 
  712. XRRecInit (XMARGSP args)
  713. {
  714.     args->options.SEAlink = 0;
  715.     args->options.SLO = 0;
  716.     args->options.Resync = 0;
  717.     args->options.MacFlow = 0;
  718.     args->options.do_CRC = 1;
  719.     args->blocknum = 0;
  720.     args->WriteBLK = 1;
  721.     args->curr_byte = 0L;
  722.     args->tries = 0;
  723.     return (XR1);
  724. }
  725.  
  726. int 
  727. XRBrecInit (XMARGSP args)
  728. {
  729.     args->options.SEAlink = 0;
  730.     args->options.SLO = 0;
  731.     args->options.Resync = 0;
  732.     args->options.MacFlow = 0;
  733.     args->options.do_CRC = 1;
  734.     args->blocknum = 0;
  735.     args->WriteBLK = 1;
  736.     args->curr_byte = 0L;
  737.     args->tries = 0;
  738.     return (XR2);
  739. }
  740.  
  741. int 
  742. XRRecStart (XMARGSP args)
  743. {
  744.     Send_NAK (args);
  745.     return (XR2);
  746. }
  747.  
  748. int 
  749. XRWaitFirst (XMARGSP args)
  750. {
  751.     long XR2Timer;
  752.  
  753.     XR2Timer = timerset (800);
  754.     if (args->tries >= 10)
  755.     {
  756.         args->goodfile = 0;
  757.         return (TIME_ERR);
  758.     }
  759.     if (args->tries == 5)
  760.     {
  761.         args->options.do_CRC = 0;
  762.         ++(args->tries);
  763.         return (XR1);
  764.     }
  765.  
  766.     while (CARRIER)
  767.     {
  768.         switch (Read_Block (args))
  769.         {
  770.         case EOT_BLOCK:
  771.             args->WriteBLK = 0;
  772.             Send_ACK (args);
  773.             return (SUCCESS_EOT);
  774.  
  775.         case TELINK_BLOCK:
  776.             if (Open_Xmodem_File (args) == -1L)
  777.                 return (OPEN_ERR);
  778.             Send_ACK (args);
  779.             args->tries = 0;
  780.             return (XR3);
  781.  
  782.         case SEALINK_BLOCK:
  783.             args->options.SEAlink = no_sealink ? 0 : 1;
  784.             if (args->options.SEAlink && !no_resync)
  785.                 args->options.Resync = (((SEADATAP) (&(args->header)))->Resync) != 0;
  786.             return (XR4);
  787.  
  788.         case XMODEM_BLOCK:
  789.             if (args->recblock == 1)
  790.             {
  791.                 if (Open_Xmodem_File (args) == -1L)
  792.                     return (OPEN_ERR);
  793.                 (void) fwrite (args->data, sizeof (unsigned char), args->datalen, args->file_pointer);
  794.  
  795.                 ++(args->WriteBLK);
  796.                 args->curr_byte = 128L;
  797.                 ++(args->blocknum);
  798.                 Send_ACK (args);
  799.                 args->tries = 0;
  800.                 return (XR3);
  801.             }
  802.  
  803.             /* Fallthrough on wrong block */
  804.  
  805.         case BAD_BLOCK:
  806.             ++(args->tries);
  807.             return (XR1);
  808.  
  809.         case CARRIER_ERR:
  810.         case KBD_ERR:
  811.             return (CARRIER_ERR);
  812.         }
  813.  
  814.         if (timeup (XR2Timer))
  815.         {
  816.             ++(args->tries);
  817.             return (XR1);
  818.         }
  819.     }
  820.  
  821.     return (CARRIER_ERR);
  822. }
  823.  
  824. int 
  825. XRWaitBlock (XMARGSP args)
  826. {
  827.     int blocknum_copy;
  828.  
  829.     if (args->tries >= 10)
  830.     {
  831.         args->goodfile = 0;
  832.         return (TIME_ERR);
  833.     }
  834.  
  835.     while (CARRIER)
  836.     {
  837.         switch (Read_Block (args))
  838.         {
  839.         case EOT_BLOCK:
  840.             args->options.SLO = 0;
  841.             Send_ACK (args);
  842.             return (SUCCESS);
  843.  
  844.         case XMODEM_BLOCK:
  845.  
  846.             blocknum_copy = (int) args->blocknum & 0xff;
  847.  
  848.             if (args->recblock == ((blocknum_copy - 1) & 0xff))
  849.             {
  850.                 --(args->blocknum);
  851.                 Send_ACK (args);
  852.                 return (XR3);
  853.             }
  854.  
  855.             if (args->recblock == blocknum_copy)
  856.             {
  857.                 (void) fwrite (args->data, sizeof (unsigned char), args->datalen, args->file_pointer);
  858.  
  859.                 ++(args->WriteBLK);
  860.                 args->curr_byte += 128L;
  861.                 Send_ACK (args);
  862.                 args->tries = 0;
  863.                 return (XR3);
  864.             }
  865.  
  866.             if (args->recblock < blocknum_copy)
  867.             {
  868.                 args->recblock += 256;
  869.             }
  870.  
  871.             if ((args->recblock > blocknum_copy) && (args->recblock <= ((blocknum_copy + 127) & 0xff)))
  872.             {
  873.                 if (args->tries != 0)
  874.                 {
  875.                     /* We have sent at least one nak, now only send them
  876.               every so often to allow buffers to drain */
  877.                     if ((args->recblock - blocknum_copy) % 16)
  878.                         return (XR3);
  879.  
  880.                     /* If it is a multiple of 16, then check that it is
  881.               higher than 32 */
  882.                     if ((args->recblock - blocknum_copy) / 16 < 2)
  883.                         return (XR3);
  884.                 }
  885.             }
  886.  
  887.             /* fallthrough on bad block */
  888.  
  889.         case BAD_BLOCK:
  890.             Send_NAK (args);
  891.             ++(args->tries);
  892.             return (XR3);
  893.  
  894.         case CARRIER_ERR:
  895.         case KBD_ERR:
  896.             return (CARRIER_ERR);
  897.         }
  898.     }
  899.  
  900.     return (CARRIER_ERR);
  901. }
  902.  
  903. int 
  904. XRRestart (XMARGSP args)
  905. {
  906.     long c;
  907.  
  908.     c = Set_Up_Restart (args);
  909.     if (c == -1L)
  910.         return (OPEN_ERR);
  911.  
  912.     if ((!c) || (!(args->options.Resync)))
  913.     {
  914.         Send_ACK (args);
  915.         args->tries = 0;
  916.     }
  917.     else
  918.     {
  919.         args->WriteBLK = c;
  920.         args->curr_byte = (c - 1) * 128L;
  921.         args->blocknum = (unsigned char) ((args->WriteBLK) & 0xff);
  922.         Send_NAK (args);
  923.     }
  924.  
  925.     return (XR5);
  926. }
  927.  
  928. int 
  929. XRSetOvrdr (XMARGSP args)
  930. {
  931.     if (!no_overdrive)
  932.         args->options.SLO = (((SEADATAP) (&(args->header)))->SLO) != 0;
  933.  
  934.     if (args->options.SLO)
  935.         show_block ((long) (args->WriteBLK - 1), " *Overdrive*", args);
  936.  
  937.     return (XR3);
  938. }
  939.  
  940. int 
  941. Xmodem_Receive_File (char *path, char *filename)
  942. {
  943.     XMARGS xmfile;
  944.     int res;
  945.  
  946.     locate_y = wherey ();
  947.     locate_x = wherex ();
  948.     (void) memset (&xmfile, 0, sizeof (XMARGS));
  949.     xmfile.path = path;
  950.     xmfile.filename = filename;
  951.     xmfile.total_blocks = -1L;
  952.     xmfile.sent_ACK = 0;
  953.     res = state_machine ((STATEP) Xmodem_Receiver, &xmfile, XR0);
  954.     return (res);
  955. }
  956.  
  957. int 
  958. Batch_Xmodem_Receive_File (char *path, char *filename)
  959. {
  960.     XMARGS xmfile;
  961.     int res;
  962.  
  963.     locate_y = wherey ();
  964.     locate_x = wherex ();
  965.     (void) memset (&xmfile, 0, sizeof (XMARGS));
  966.     xmfile.path = path;
  967.     xmfile.filename = filename;
  968.     xmfile.total_blocks = -1L;
  969.     xmfile.sent_ACK = 0;
  970.     res = state_machine ((STATEP) Xmodem_Receiver, &xmfile, XR0B);
  971.     return (res);
  972. }
  973.  
  974. int SAInit (XMARGSP);
  975. int SAEnd (XMARGSP);
  976. int SAClearLine (XMARGSP);
  977. int SASendACK (XMARGSP);
  978. int SASEAlink (XMARGSP);
  979. int SAIncBlk (XMARGSP);
  980.  
  981. typedef struct
  982. {
  983.     char *state_name;
  984.     int (*state_func) (XMARGSP);
  985. } ASTATES, *ASTATEP;
  986.  
  987. ASTATES ACK_States[] =
  988. {
  989.     {"SAInit", SAInit},
  990.     {"SAEnd", SAEnd},
  991.     {"SA0", SAClearLine},
  992.     {"SA1", SASendACK},
  993.     {"SA2", SASEAlink},
  994.     {"SA3", SAIncBlk}
  995. };
  996.  
  997. int 
  998. SAInit (XMARGSP args)
  999. {
  1000.     return ((int) args->control);
  1001. }
  1002.  
  1003. int 
  1004. SAEnd (XMARGSP args)
  1005. {
  1006.     return ((int) args->control);
  1007. }
  1008.  
  1009. int 
  1010. SAClearLine (XMARGSP args)
  1011. {
  1012.     long SA0Timer;
  1013.  
  1014.     SA0Timer = timerset (3000);
  1015.     if (args->options.SLO)
  1016.         return (SA3);
  1017.  
  1018.     if (args->options.SEAlink)
  1019.         return (SA1);
  1020.  
  1021.     while (CARRIER && !timeup (SA0Timer))
  1022.     {
  1023.         if (PEEKBYTE () >= 0)
  1024.         {
  1025.             (void) TIMED_READ (0);
  1026.             time_release ();
  1027.             continue;
  1028.         }
  1029.  
  1030.         return (SA1);
  1031.     }
  1032.  
  1033.     return (TIME_ERR);
  1034. }
  1035.  
  1036. int 
  1037. SASendACK (XMARGSP args)
  1038. {
  1039.     SENDBYTE (ACK);
  1040.     args->sent_ACK = 1;
  1041.     return (SA2);
  1042. }
  1043.  
  1044. int 
  1045. SASEAlink (XMARGSP args)
  1046. {
  1047.     if (!(args->options.SEAlink))
  1048.         return (SA3);
  1049.  
  1050.     SENDBYTE (args->blocknum);
  1051.     SENDBYTE ((unsigned char) ~(args->blocknum));
  1052.     return (SA3);
  1053. }
  1054.  
  1055. void 
  1056. show_block (long b, char *c, XMARGSP args)
  1057. {
  1058.     char j[100];
  1059.     long k;
  1060.  
  1061.     if (fullscreen && un_attended)
  1062.     {
  1063.         elapse_time ();
  1064.  
  1065.         sb_move (filewin, 2, 2);
  1066.         sb_puts (filewin, ultoa (((unsigned long) b), e_input, 10));
  1067.         if (c)
  1068.             sb_puts (filewin, c);
  1069.  
  1070.         k = args->filelen - args->curr_byte;
  1071.         if (k < 0L)
  1072.             k = 0L;
  1073.  
  1074.         (void) sprintf (j, "%3ld min",
  1075.             ((k * 10L / cur_baud.rate_value * 100L /
  1076.             ((args->save_header == SOH) ? 94L : 70L) + 59L) / 60L));
  1077.  
  1078.         sb_move (filewin, 2, 69);
  1079.         sb_puts (filewin, j);
  1080.         sb_show ();
  1081.     }
  1082.     else
  1083.     {
  1084.         gotoxy (locate_x, locate_y);
  1085.         (void) printf ("%s", ultoa (((unsigned long) b), e_input, 10));
  1086.         if (c)
  1087.             (void) printf ("%s", c);
  1088.     }
  1089. }
  1090.  
  1091. int 
  1092. SAIncBlk (XMARGSP args)
  1093. {
  1094.     ++(args->blocknum);
  1095.     if ((args->options.SLO) &&
  1096.         (((args->WriteBLK > 0) && (!((args->WriteBLK - 1) & 0x001F)) && (args->WriteBLK < args->total_blocks)) ||
  1097.             (args->WriteBLK >= args->total_blocks)))
  1098.     {
  1099.         show_block ((long) (args->WriteBLK - 1), " *Overdrive*", args);
  1100.     }
  1101.     else if ((!(args->options.SLO)) && (args->WriteBLK > 0))
  1102.     {
  1103.         show_block ((long) (args->WriteBLK - 1), NULL, args);
  1104.     }
  1105.  
  1106.     return (SUCCESS);
  1107. }
  1108.  
  1109. void 
  1110. Send_ACK (XMARGSP args)
  1111. {
  1112.     (void) state_machine ((STATEP) ACK_States, args, SA0);
  1113. }
  1114.  
  1115. void Send_Resync_Packet (XMARGSP);
  1116.  
  1117. int SNInit (XMARGSP);
  1118. int SNEnd (XMARGSP);
  1119. int SNClearLine (XMARGSP);
  1120. int SNSendNAK (XMARGSP);
  1121. int SNSEAlink (XMARGSP);
  1122. int SNAckResync (XMARGSP);
  1123.  
  1124. typedef struct
  1125. {
  1126.     char *state_name;
  1127.     int (*state_func) (XMARGSP);
  1128. } NSTATES, *NSTATEP;
  1129.  
  1130. NSTATES NAK_States[] =
  1131. {
  1132.     {"SNInit", SNInit},
  1133.     {"SNEnd", SNEnd},
  1134.     {"SN0", SNClearLine},
  1135.     {"SN1", SNSendNAK},
  1136.     {"SN2", SNSEAlink},
  1137.     {"SN3", SNAckResync}
  1138. };
  1139.  
  1140. int 
  1141. SNInit (XMARGSP args)
  1142. {
  1143.     return ((int) args->control);
  1144. }
  1145.  
  1146. int 
  1147. SNEnd (XMARGSP args)
  1148. {
  1149.     return ((int) args->control);
  1150. }
  1151.  
  1152. int 
  1153. SNClearLine (XMARGSP args)
  1154. {
  1155.     long SN0Timer;
  1156.  
  1157.     SN0Timer = timerset (3000);
  1158.     if (args->options.Resync)
  1159.     {
  1160.         Send_Resync_Packet (args);
  1161.         return (SN3);
  1162.     }
  1163.  
  1164.     if (args->options.SEAlink)
  1165.         return (SN1);
  1166.  
  1167.     while (CARRIER && !timeup (SN0Timer))
  1168.     {
  1169.         if (PEEKBYTE () >= 0)
  1170.         {
  1171.             (void) TIMED_READ (0);
  1172.             time_release ();
  1173.             continue;
  1174.         }
  1175.  
  1176.         return (SN1);
  1177.     }
  1178.  
  1179.     return (TIME_ERR);
  1180. }
  1181.  
  1182. int 
  1183. SNSendNAK (XMARGSP args)
  1184. {
  1185.     if (args->options.do_CRC && (args->sent_ACK == 0))
  1186.         SENDBYTE (WANTCRC);
  1187.     else
  1188.         SENDBYTE (NAK);
  1189.     return (SN2);
  1190. }
  1191.  
  1192. int 
  1193. SNSEAlink (XMARGSP args)
  1194. {
  1195.     if (!(args->options.SEAlink))
  1196.         return (SUCCESS);
  1197.  
  1198.     SENDBYTE (args->blocknum);
  1199.     SENDBYTE ((unsigned char) ~(args->blocknum));
  1200.     return (SUCCESS);
  1201. }
  1202.  
  1203. int 
  1204. SNAckResync (XMARGSP args)
  1205. {
  1206.     long SN3Timer;
  1207.     int c;
  1208.  
  1209.     SN3Timer = timerset (3000);
  1210.  
  1211.     while (CARRIER && !timeup (SN3Timer))
  1212.     {
  1213.         if ((unsigned int) (c = TIMED_READ (10)) == 0xffff)
  1214.         {
  1215.             Send_Resync_Packet (args);
  1216.             continue;
  1217.         }
  1218.  
  1219.         if (c == ACK)
  1220.         {
  1221.             big_pause (1);
  1222.             c = PEEKBYTE ();
  1223.             if ((c == SOH) || (c == EOT))
  1224.                 return (SUCCESS);
  1225.         }
  1226.     }
  1227.  
  1228.     if (!CARRIER)
  1229.         return (CARRIER_ERR);
  1230.     else
  1231.         return (TIME_ERR);
  1232. }
  1233.  
  1234. void 
  1235. Send_NAK (XMARGSP args)
  1236. {
  1237.     (void) state_machine ((STATEP) NAK_States, args, SN0);
  1238. }
  1239.  
  1240. void 
  1241. Send_Resync_Packet (XMARGSP args)
  1242. {
  1243.     unsigned char resyncit[30];
  1244.     unsigned short nak_crc;
  1245.  
  1246.     SENDBYTE (SYN);
  1247.     (void) sprintf ((char *) resyncit, "%ld", args->WriteBLK);
  1248.     SENDCHARS ((char *) resyncit, strlen ((char *) resyncit), 1);
  1249.     nak_crc = crc_block ((unsigned char *) resyncit, (int) strlen ((char *) resyncit));
  1250.     SENDBYTE (ETX);
  1251.     SENDBYTE ((unsigned char) (nak_crc & 0xff));
  1252.     CLEAR_INBOUND ();
  1253.     SENDBYTE ((unsigned char) (nak_crc >> 8));
  1254. }
  1255.  
  1256. void 
  1257. Xmodem_Error (char *s, long block_number)
  1258. {
  1259.     char j[50];
  1260.     char k[50];
  1261.  
  1262.     (void) sprintf (j, "%s %s %ld", s, MSG_TXT (M_ON_BLOCK), block_number);
  1263.     (void) sprintf (k, "%-49.49s", j);
  1264.  
  1265.     status_line (">Xmodem Error: %s", k);
  1266.     if (fullscreen && un_attended)
  1267.     {
  1268.         sb_move (filewin, 2, 20);
  1269.         sb_puts (filewin, k);
  1270.         sb_show ();
  1271.     }
  1272.     else
  1273.     {
  1274.         gotoxy (locate_x + 20, locate_y);
  1275.         (void) cputs (k);
  1276.     }
  1277. }
  1278.  
  1279. void 
  1280. Find_Char (int c)
  1281. {
  1282.     long t1;
  1283.     long t2;
  1284.  
  1285.     t1 = timerset (3000);
  1286.     t2 = timerset (100);
  1287.     while (!timeup (t1) && !timeup (t2))
  1288.     {
  1289.         if (!CARRIER)
  1290.             break;
  1291.  
  1292.         if (PEEKBYTE () == (c & 0xff))
  1293.             break;
  1294.         else if (PEEKBYTE () >= 0)
  1295.         {
  1296.             (void) TIMED_READ (0);
  1297.             t2 = timerset (100);
  1298.         }
  1299.     }
  1300. }
  1301.  
  1302. int 
  1303. Header_in_data (unsigned char *p)
  1304. {
  1305.     int i;
  1306.     int j;
  1307.     char *p1;
  1308.  
  1309.     p1 = (char *) p;
  1310.     ++p1;
  1311.     j = sizeof (XMDATA) - 2;
  1312.     for (i = 1; i < j; i++, p1++)
  1313.     {
  1314.         if (*p1 == SOH)
  1315.         {
  1316.             (void) memcpy (p, p1, (unsigned int) (j - i));
  1317.             return (j - i);
  1318.         }
  1319.     }
  1320.  
  1321.     return (0);
  1322. }
  1323.